﻿
#include "timeCalc.h"

#include <stdio.h>
#include <string.h>
#include <Windows.h>
#include <QDebug>
#include <QDateTime>

#ifdef __MINGW32__ //w32api bug
#  define TIME_KILL_SYNCHRONOUS 0x0100
#endif

#define kTimeTick  2

//void WINAPI CALLBACK mmtimer_proc(uint timerId, uint, DWORD_PTR user, DWORD_PTR, DWORD_PTR)
//{
//    MMTimer *t = reinterpret_cast(user);
//    emit t->timeout();
//}

//MMRESULT timeSetEvent( UINT uDelay ,      //以毫秒指定事件的周期。
//                    UINT uResolution ,    //以毫秒指定延时的精度，数值越小定时器事件分辨率越高。缺省值为1ms。
//                    LPTIMECALLBACK fptc ,
//                    DWORD dwUser ,        //存放用户提供的回调数据。
//                    UINT fuEvent );       //指定定时器事件类型：TIME_ONESHOT：uDelay毫秒后只产生一次事件,TIME_PERIODIC ：每隔uDelay毫秒周期性地产生事件。

uint32_t TimeCacle::uTimeTick=0;

void WINAPI onTimeFunc(UINT wTimerID, UINT msg,DWORD_PTR dwUser,DWORD dwl,DWORD dw2)
{
    TimeCacle::uTimeTick += kTimeTick;
    TimeCacle *t = (TimeCacle *)dwUser;//reinterpret_cast(dwUser);

    t->emitTimeout();
}


TimeCacle::TimeCacle():m_bStart(false)
{
    m_startMs=0;
    m_mode == CM_GET;
}
	
TimeCacle::~TimeCacle()
{
	Stop();
}

void TimeCacle::emitTimeout()
{
   emit timeout();
}
void TimeCacle::Resum(uint32_t timeTick)
{
    if(!m_bStart)
    {
        if(m_mode == CM_ADD)
        {
            uTimeTick += timeTick;
            m_timerId = timeSetEvent(kTimeTick, 1, (LPTIMECALLBACK)onTimeFunc, (DWORD_PTR)this, TIME_PERIODIC);//TIME_CALLBACK_FUNCTION | TIME_PERIODIC | TIME_KILL_SYNCHRONOUS
            if(NULL == m_timerId)
            {
                printf("timeSetEvent() failed with error %d\n", GetLastError());
                return ;
            }
        }
        else
        {
            if(m_startMs == 0)
            {
                m_startMs = QDateTime::currentMSecsSinceEpoch();
            }
            else
            {
                qint64 tms= QDateTime::currentMSecsSinceEpoch();

                m_startMs += (tms-m_resumMs);
            }

            m_startMs -= timeTick;
        }
        m_bStart=true;
    }
}

void TimeCacle::Start(uint32_t timeTick)
{
	if(!m_bStart)
	{
        if(m_mode == CM_ADD)
        {
            uTimeTick=timeTick;
            m_timerId = timeSetEvent(kTimeTick, 1, (LPTIMECALLBACK)onTimeFunc, (DWORD_PTR)this, TIME_PERIODIC);//TIME_CALLBACK_FUNCTION | TIME_PERIODIC | TIME_KILL_SYNCHRONOUS
            if(NULL == m_timerId)
            {
                printf("timeSetEvent() failed with error %d\n", GetLastError());
                return ;
            }
        }
        else
        {
            m_startMs = QDateTime::currentMSecsSinceEpoch();
            m_startMs -= timeTick;
        }
        m_bStart=true;
	}
}

uint32_t TimeCacle::GetTimeString(QString &tmString, QString &msecString)
{
    uint32_t tmpTick;
    if(m_mode == CM_ADD)
    {
        tmpTick = uTimeTick;
    }
    else
    {
        if(m_startMs == 0)
        {
            tmpTick=0;
        }
        else
        {
            tmpTick = QDateTime::currentMSecsSinceEpoch() - m_startMs;
        }

        //qDebug()<<tmpTick;
    }

    //qDebug()<<tmpTick;

    Format(tmString,msecString,tmpTick);
    return tmpTick;
}

void TimeCacle::Format(QString &tmString,QString &msecString,const uint32_t msecTick)
{
    //hh:mm:ss:xxx
    char timeBuff[128];

    uint32_t sec = msecTick/1000;
    uint32_t msec = msecTick%1000;

    uint32_t min = sec/60;
    sec = sec%60;

    uint32_t hour = min/60;
    min = min%60;

    sprintf(timeBuff,"%02d:%02d:%02d",hour,min,sec);
    tmString = timeBuff;

    sprintf(timeBuff,"%03d",msec);
    msecString=timeBuff;

    //qDebug()<<timeBuff;
}

void TimeCacle::Stop()
{
	if(m_bStart)
	{
		timeKillEvent(m_timerId);        //释放定时器
		m_bStart=false;
        m_resumMs=QDateTime::currentMSecsSinceEpoch();
	}
}
